<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>

  <script>
    // 这只是一个很简单的发布订阅模式
    // 现在还有这很多的地方有问题，比如：
    // 1. 事件在注销时会连带的将数组给清空，导致删除了其他的回调函数
    // 2. once事件时，也容易造成这样的结果，就是删除了其他的回调函数
    // 3. 以及一些边界问题没有处理
    // 4. 还有一些参数问题没有处理
    class MyEvent {
      #handlers = {};

      $on(event, callback) {
        if (!this.#handlers[event]) {
          this.#handlers[event] = [];
        }

        this.#handlers[event].push(callback);
      }

      $emit(event, ...args) {
        const callbacks = this.#handlers[event] || [];

        callbacks.forEach(callback => {
          callback(...args);
        })
      }

      $off(event) {
        this.#handlers[event] = undefined;
      }

      $once(event, callback) {
        $on(event, (...args) => {
          callback(...args);
          this.$off(event);
        })
      }
    }

  </script>
</body>

</html>